﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace TUtils
{
	/// <summary>
	/// thread-safe instantiation of a singleton
	/// </summary>
	/// <remarks>
	/// <example>
	/// simple singleton
	/// <code><![CDATA[
	/// public class MySingleton : TSingleton<MySingleton>
	/// {
	/// 	public void HelloWorld()
	/// 	{
	/// 	}
	/// }
	/// 
	/// public class Test
	/// {
	/// 	public static void Test1()
	/// 	{
	/// 		MySingleton.Instance.HelloWorld();
	/// 	}
	/// }
	/// ]]></code>
	/// 
	/// singleton class derived from a base class
	/// <code><![CDATA[
	/// public class MyClass : MyBaseClass
	/// {
	/// 	public void HelloWorld()
	/// 	{
	/// 	}
	/// }
	/// 
	/// public class MySingletonDerived : TSingleton<MyClass>
	/// {
	/// }
	/// 
	/// public class Test
	/// {
	/// 	public static void Test1()
	/// 	{
	/// 		MySingletonDerived.Instance.HelloWorld();
	/// 	}
	/// }
	/// ]]></code>
	/// </example>
	/// </remarks>
	/// <typeparam name="T"></typeparam>
	public class TSingleton<T> where T : class, new()
	{
		#region === Inner classes & structs =====================================================================

			/// <summary>
			/// Nested class that can be acces by parent class only.
			/// Holds the instance of the singleton and ensures thread-saftey by using a static constructor (faster
			/// than locking).
			/// </summary>
			private class Nested
			{ 

				#region === Variables & Properties =====================================================================

					/// <summary>Holds the singelton reference</summary>
					internal static T instance = new T();

				#endregion

				#region === Constructors =====================================================================

					/// <summary>
					/// Default constructor of nested class.
					/// Explicit static to tell the compiler not to mark type as befroefieldinit.
					/// </summary>
					static Nested()
					{
						
					}

				#endregion

			}

		#endregion

		#region === Variables & Properties =====================================================================

			/// <summary>
			/// The instance of the singelton class
			/// </summary>
			public static T Instance
			{
				get
				{
					if ( Nested.instance == null )
						Nested.instance = new T(); // because setter could have set it to null.
					return Nested.instance;
				}
				protected set
				{
					Nested.instance = value;
				}
			}

		#endregion

	}
}
